/**
 * @file demo_modbus_usage.cpp
 * @brief Modbus RTU 通信层使用示例
 *
 * 本文件演示如何使用 Modbus RTU 通信层完成以下任务：
 * 1. 扫描和打开串口
 * 2. 读取单个电表数据
 * 3. 配置3条总线并行轮询
 * 4. 处理电表数据更新
 */

#include <QCoreApplication>
#include <QTimer>
#include <QDebug>
#include "../src/io/serialportmanager.h"
#include "../src/io/modbusmaster.h"
#include "../src/io/pollscheduler.h"
#include "../src/core/meter.h"
#include "../src/utils/logger.h"
#include "../src/utils/config.h"

class ModbusDemo : public QObject
{
    Q_OBJECT

public:
    ModbusDemo(QObject *parent = nullptr) : QObject(parent)
    {
        m_portManager = new SerialPortManager(this);
        m_scheduler = nullptr;
    }

    ~ModbusDemo()
    {
        if (m_scheduler)
        {
            m_scheduler->stopPolling();
        }
    }

    /**
     * @brief 示例1: 扫描串口
     */
    void demo1_ScanPorts()
    {
        qDebug() << "\n========== 示例1: 扫描串口 ==========";

        QStringList ports = m_portManager->scanAvailablePorts();
        qDebug() << "发现" << ports.size() << "个串口:";
        for (const QString &port : ports)
        {
            qDebug() << "  -" << port;
        }
    }

    /**
     * @brief 示例2: 读取单个电表数据
     */
    void demo2_ReadSingleMeter()
    {
        qDebug() << "\n========== 示例2: 读取单个电表 ==========";

        // 打开串口（请根据实际情况修改串口名称）
        QString portName = "COM3"; // Windows
        // QString portName = "/dev/ttyUSB0";  // Linux

        if (!m_portManager->openPort(portName, 115200))
        {
            qDebug() << "无法打开串口" << portName;
            return;
        }

        qDebug() << "成功打开串口:" << portName;

        // 创建Modbus主站
        QSerialPort *port = m_portManager->getPort(portName);
        ModbusMaster master(port);

        // 读取站号1的电表
        qDebug() << "正在读取站号1的电表...";
        ModbusMaster::ModbusResponse response = master.readMeterData(1);

        if (response.success)
        {
            qDebug() << "读取成功!";
            qDebug() << "  Ua =" << response.data[0] * 0.1 << "V";
            qDebug() << "  Ub =" << response.data[1] * 0.1 << "V";
            qDebug() << "  Uc =" << response.data[2] * 0.1 << "V";
            qDebug() << "  Ia =" << response.data[3] * 0.001 << "A";
            qDebug() << "  Ib =" << response.data[4] * 0.001 << "A";
            qDebug() << "  Ic =" << response.data[5] * 0.001 << "A";
        }
        else
        {
            qDebug() << "读取失败:" << response.errorMessage;
        }

        m_portManager->closePort(portName);
    }

    /**
     * @brief 示例3: 配置3条总线并行轮询
     */
    void demo3_PollScheduler()
    {
        qDebug() << "\n========== 示例3: 3条总线并行轮询 ==========";

        // 配置3条总线（请根据实际情况修改）
        struct BusConfig
        {
            int busId;
            QString portName;
            int startSlaveId;
            int endSlaveId;
        };

        QVector<BusConfig> busConfigs = {
            {1, "COM3", 1, 40},  // 配电室A: 站号1-40
            {2, "COM4", 41, 80}, // 配电室B: 站号41-80
            {3, "COM5", 81, 120} // 配电室C: 站号81-120
        };

        // 打开所有串口
        for (const BusConfig &config : busConfigs)
        {
            if (!m_portManager->openPort(config.portName, 115200))
            {
                qDebug() << "无法打开串口" << config.portName << "，跳过总线" << config.busId;
                continue;
            }
            qDebug() << "总线" << config.busId << ":" << config.portName << "打开成功";
        }

        // 创建电表对象
        m_allMeters.clear();
        for (const BusConfig &config : busConfigs)
        {
            QVector<Meter *> busMeters;
            for (int slaveId = config.startSlaveId; slaveId <= config.endSlaveId; ++slaveId)
            {
                QString name = QString("配电室%1-%2号表")
                                   .arg(QChar('A' + config.busId - 1))
                                   .arg(slaveId - config.startSlaveId + 1);
                Meter *meter = new Meter(slaveId, name, config.busId, this);
                busMeters.append(meter);
                m_allMeters.append(meter);

                // 连接数据更新信号
                connect(meter, &Meter::dataUpdated, this, [meter]()
                        { qDebug() << QString("[%1] Ua=%.1fV, Ia=%.3fA")
                                          .arg(meter->name())
                                          .arg(meter->ua())
                                          .arg(meter->ia()); });
            }

            // 将总线添加到调度器
            if (!m_scheduler)
            {
                m_scheduler = new PollScheduler(m_portManager, this);
            }
            m_scheduler->addBus(config.busId, config.portName, busMeters);
        }

        // 设置轮询间隔500ms
        m_scheduler->setPollInterval(500);

        // 连接调度器信号
        connect(m_scheduler, &PollScheduler::busPollCompleted,
                this, [](int busId, int successCount, int totalCount)
                { qDebug() << QString("总线%1轮询完成: %2/%3 成功")
                                  .arg(busId)
                                  .arg(successCount)
                                  .arg(totalCount); });

        // 启动轮询
        qDebug() << "启动轮询调度器...";
        m_scheduler->startPolling();

        qDebug() << "轮询已启动，按Ctrl+C停止";

        // 10秒后自动停止（用于演示）
        QTimer::singleShot(10000, this, [this]()
                           {
            qDebug() << "\n10秒演示结束，停止轮询";
            if (m_scheduler) {
                m_scheduler->stopPolling();
            }
            QCoreApplication::quit(); });
    }

    /**
     * @brief 示例4: 使用配置文件
     */
    void demo4_UseConfig()
    {
        qDebug() << "\n========== 示例4: 使用配置文件 ==========";

        // 读取配置文件（使用绝对路径）
        Config *config = Config::instance();
        // 注意：Config 类的默认路径已经是绝对路径，这里仅演示用法

        // 获取串口配置（使用便捷方法）
        QString port1 = config->getSerialPort1();
        QString port2 = config->getSerialPort2();
        QString port3 = config->getSerialPort3();
        int baudRate = config->getBaudRate();

        qDebug() << "配置文件设置:";
        qDebug() << "  串口1:" << port1;
        qDebug() << "  串口2:" << port2;
        qDebug() << "  串口3:" << port3;
        qDebug() << "  波特率:" << baudRate;

        // 获取轮询配置
        int pollInterval = config->getPollInterval();
        int timeout = config->getModbusTimeout();

        qDebug() << "  轮询间隔:" << pollInterval << "ms";
        qDebug() << "  超时时间:" << timeout << "ms";
    }

private:
    SerialPortManager *m_portManager;
    PollScheduler *m_scheduler;
    QVector<Meter *> m_allMeters;
};

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    // 初始化日志系统
    Logger::instance()->log(LogLevel::Info, "Modbus RTU 使用示例启动");

    ModbusDemo demo;

    // 运行示例（请取消注释您想运行的示例）

    // demo.demo1_ScanPorts();
    // demo.demo2_ReadSingleMeter();
    // demo.demo3_PollScheduler();
    demo.demo4_UseConfig();

    // 如果运行示例3，需要启动事件循环
    // return app.exec();

    return 0;
}

#include "demo_modbus_usage.moc"
